﻿using System;
using System.Net;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Silverlight.ControlToolkit.Converters;
using System.Windows.Controls.Primitives;

namespace Silverlight.ControlToolkit.ControlService
{
    public class DirtyReadTracker
    {
        #region Attached Properties

        #region TrackDirtyRead

        public static readonly DependencyProperty TrackDirtyReadProperty =
                DependencyProperty.RegisterAttached("TrackDirtyRead", typeof(bool), typeof(DirtyReadTracker),
                                                    new PropertyMetadata(OnTrackDirtyReadChanged));

        /// <summary>
        /// Gets the current TrackDirtyRead associated with the control
        /// </summary>
        /// <param name="d">Dependecy Object / Control</param>
        /// <returns></returns>
        public static bool GetTrackDirtyRead(DependencyObject d)
        {
            return (bool)d.GetValue(TrackDirtyReadProperty);
        }

        /// <summary>
        /// Sets the Data Type property
        /// </summary>
        /// <param name="d">Dependecy Object / Control</param>
        /// <param name="value">Data Type to be set on the control</param>
        public static void SetTrackDirtyRead(DependencyObject d, bool value)
        {
            d.SetValue(TrackDirtyReadProperty, value);
        }

        /// <summary>
        /// Handles changes to the TrackDirtyRead property.
        /// </summary>
        /// <param name="d">Dependecy Object / Control</param>
        /// <param name="e">Event args</param>
        private static void OnTrackDirtyReadChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {

            if (e.OldValue != null)
            {
                if (d is TextBox) //TextBox control
                {
                    TextBox textBox = d as TextBox;
                    textBox.TextChanged -= new TextChangedEventHandler(textBox_TextChanged);
                }
                else if (d is Selector)
                {
                    Selector selectList = d as Selector;
                    selectList.SelectionChanged -= new SelectionChangedEventHandler(selectList_SelectionChanged);
                }
                else if (d is ButtonBase)
                {
                    ButtonBase button = d as ButtonBase;
                    button.Click -= new RoutedEventHandler(button_Click);
                }

            }

            //Add handler if DataType is set
            if ((bool)e.NewValue)
            {
                if (d is TextBox) //TextBox control
                {
                    TextBox textBox = d as TextBox;
                    textBox.TextChanged += new TextChangedEventHandler(textBox_TextChanged);
                }
                else if (d is Selector)
                {
                    Selector selectList = d as Selector;
                    selectList.SelectionChanged += new SelectionChangedEventHandler(selectList_SelectionChanged);
                }
                else if (d is ButtonBase)
                {
                    ButtonBase button = d as ButtonBase;
                    button.Click += new RoutedEventHandler(button_Click);
                }
                else if (d is Panel && (!TrackDirtyReadOnAllChild(d)))
                {
                    ((Panel)d).Loaded += new RoutedEventHandler(DirtyReadTracker_Loaded);
                }

            }



        }

        static void DirtyReadTracker_Loaded(object sender, RoutedEventArgs e)
        {
            DependencyObject d = sender as DependencyObject;

            if (d != null)
            {
                TrackDirtyReadOnAllChild(d);
            }

            ((Panel)d).Loaded -= new RoutedEventHandler(DirtyReadTracker_Loaded);
        }

        private static bool TrackDirtyReadOnAllChild(DependencyObject d)
        {
            bool results = false;

            if (d != null)
            {
                bool value = GetTrackDirtyRead(d);

                foreach (DependencyObject curChild in d.GetVisualChildren())
                {
                    results = true;

                    if ((curChild is TextBox || curChild is Selector))
                    {
                        SetTrackDirtyRead(curChild, value);
                    }
                }
            }

            return results;

        }

        private static void SetDirtyReadOnContainer(DependencyObject controlChanged)
        {

            if (!GetIsDirty(controlChanged as DependencyObject))
            {
                SetIsDirty(controlChanged as DependencyObject, true);

                if (controlChanged is FrameworkElement)
                {
                    IList<FrameworkElement> allParents = Utilities.GetAllParents(controlChanged as FrameworkElement);

                    foreach (FrameworkElement currentElement in allParents)
                    {
                        if (currentElement is DependencyObject && GetTrackDirtyRead(currentElement as DependencyObject))
                        {
                            SetIsDirty(currentElement as DependencyObject, true);
                        }

                    }
                }
            
            }
            

        }

        static void button_Click(object sender, RoutedEventArgs e)
        {
            if (sender is DependencyObject)
            {
                SetDirtyReadOnContainer(sender as DependencyObject);
            }
        }

        static void selectList_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (sender is DependencyObject)
            {
                SetDirtyReadOnContainer(sender as DependencyObject);
            }
        }

        static void textBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (sender is DependencyObject)
            {
                SetDirtyReadOnContainer(sender as DependencyObject);
            }
        }


        #endregion


        #region IsDirty

        public static readonly DependencyProperty IsDirtyProperty =
            DependencyProperty.RegisterAttached("IsDirty", typeof(bool), typeof(DirtyReadTracker), null);

        /// <summary>
        /// Gets the current datatype associated with the control
        /// </summary>
        /// <param name="d">Dependecy Object / Control</param>
        /// <returns></returns>
        public static bool GetIsDirty(DependencyObject d)
        {
            return (bool)d.GetValue(IsDirtyProperty);
        }

        /// <summary>
        /// Sets the Data Type property
        /// </summary>
        /// <param name="d">Dependecy Object / Control</param>
        /// <param name="value">Data Type to be set on the control</param>
        public static void SetIsDirty(DependencyObject d, bool value)
        {
            d.SetValue(IsDirtyProperty, value);

        }


        #endregion

        #endregion
        

    }
}
